package com.r2coding.infrastructure.persistent.repository;

import com.r2coding.domain.strategy.model.entity.StrategyAwardEntity;
import com.r2coding.domain.strategy.model.entity.StrategyEntity;
import com.r2coding.domain.strategy.model.entity.StrategyRuleEntity;
import com.r2coding.domain.strategy.model.valobj.StrategyAwardRuleModelVO;
import com.r2coding.domain.strategy.repository.IStrategyRepository;
import com.r2coding.infrastructure.persistent.dao.IStrategyAwardDao;
import com.r2coding.infrastructure.persistent.dao.IStrategyDao;
import com.r2coding.infrastructure.persistent.dao.IStrategyRuleDao;
import com.r2coding.infrastructure.persistent.po.Strategy;
import com.r2coding.infrastructure.persistent.po.StrategyAward;
import com.r2coding.infrastructure.persistent.po.StrategyRule;
import com.r2coding.infrastructure.persistent.redis.IRedisService;
import com.r2coding.types.common.Constants;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 抽奖策略仓储服务 实现类
 *
 * @author caolx
 * @date 2025/7/25 7:31
 */
@Repository
public class StrategyRepository implements IStrategyRepository {

    /**
     * Redis服务（提供者为：Redisson）
     */
    @Resource(name = "redissonService")
    private IRedisService redisService;
    /**
     * 抽奖策略 Dao
     */
    @Resource
    private IStrategyDao strategyDao;
    /**
     * 策略奖品 Dao
     */
    @Resource
    private IStrategyAwardDao strategyAwardDao;
    /**
     * 抽奖规则 Dao
     */
    @Resource
    private IStrategyRuleDao strategyRuleDao;

    @Override
    public List<StrategyAwardEntity> queryStrategyAwardList(Long strategyId) {
        List<StrategyAward> strategyAwardList = strategyAwardDao.queryStrategyAwardList(strategyId);

        List<StrategyAwardEntity> result = new ArrayList<>();
        for (StrategyAward strategyAward : strategyAwardList) {
            StrategyAwardEntity strategyAwardEntity = StrategyAwardEntity.builder()
                    .strategyId(strategyId)
                    .awardId(strategyAward.getAwardId())
                    .awardRate(strategyAward.getAwardRate())
                    .build();
            result.add(strategyAwardEntity);
        }
        return result;
    }

    @Override
    public void storeStrategyAwardSearchRateTable(Long strategyId, BigDecimal rateRange, Map<Integer, Integer> shuffleStrategyAwardSearchRateTable) {
        // 1、存储抽奖概率范围值，用于生成[1，范围值)内的随机概率数
        String rangeCacheKey = String.format(Constants.RedisKey.STRATEGY_RATE_RANGE_KEY, strategyId);
        redisService.setValue(rangeCacheKey, rateRange.intValue());

        // 2、存储概率查找表
        String rateTableCacheKey = String.format(Constants.RedisKey.STRATEGY_RATE_SEARCH_TABLE_KET, strategyId);
        redisService.getMap(rateTableCacheKey).putAll(shuffleStrategyAwardSearchRateTable);
    }

    @Override
    public void storeStrategyWeightAwardSearchRateTable(Long strategyId, Integer ruleWeight, BigDecimal rateRange, Map<Integer, Integer> shuffleStrategyAwardSearchRateTable) {
        // 1、存储抽奖概率范围值，用于生成[1，范围值)内的随机概率数
        String rangeCacheKey = String.format(Constants.RedisKey.STRATEGY_RATE_WEIGHT_RANGE_KEY, strategyId, ruleWeight);
        redisService.setValue(rangeCacheKey, rateRange.intValue());

        // 2、存储概率查找表
        String rateTableCacheKey = String.format(Constants.RedisKey.STRATEGY_RATE_WEIGHT_SEARCH_TABLE_KET, strategyId, ruleWeight);
        redisService.getMap(rateTableCacheKey).putAll(shuffleStrategyAwardSearchRateTable);
    }

    @Override
    public Integer getRateRange(Long strategyId) {
        String rangeCacheKey = String.format(Constants.RedisKey.STRATEGY_RATE_RANGE_KEY, strategyId);
        return redisService.getValue(rangeCacheKey);
    }

    @Override
    public Integer getRuleWeightRateRange(Long strategyId, Integer ruleWeight) {
        String rangeCacheKey = String.format(Constants.RedisKey.STRATEGY_RATE_WEIGHT_RANGE_KEY, strategyId, ruleWeight);
        return redisService.getValue(rangeCacheKey);
    }

    @Override
    public Integer getStrategyAwardAssemble(Long strategyId, Integer rateKey) {
        String rateTableCacheKey = String.format(Constants.RedisKey.STRATEGY_RATE_SEARCH_TABLE_KET, strategyId);
        return redisService.getFromMap(rateTableCacheKey, rateKey);
    }

    @Override
    public Integer getStrategyWeightAwardAssemble(Long strategyId, Integer ruleWeight, Integer rateKey) {
        String rateTableCacheKey = String.format(Constants.RedisKey.STRATEGY_RATE_WEIGHT_SEARCH_TABLE_KET, strategyId, ruleWeight);
        return redisService.getFromMap(rateTableCacheKey, rateKey);
    }

    @Override
    public StrategyEntity queryStrategyEntity(Long strategyId) {
        Strategy strategy = strategyDao.queryStrategy(strategyId);
        return StrategyEntity.builder()
                .strategyId(strategyId)
                .strategyDesc(strategy.getStrategyDesc())
                .ruleModels(strategy.getRuleModels())
                .build();
    }

    @Override
    public StrategyRuleEntity queryStrategyRuleEntity(Long strategyId, String ruleModel) {
        StrategyRule strategyRule = strategyRuleDao.queryStrategyRule(strategyId, ruleModel);
        return StrategyRuleEntity.builder()
                .strategyId(strategyRule.getStrategyId())
                .awardId(strategyRule.getAwardId())
                .ruleType(strategyRule.getRuleType())
                .ruleModel(strategyRule.getRuleModel())
                .ruleValue(strategyRule.getRuleValue())
                .ruleDesc(strategyRule.getRuleDesc())
                .build();

    }

    @Override
    public String queryStrategyRuleValue(Long strategyId, Integer awardId, String ruleModel) {
        return strategyRuleDao.queryStrategyRuleValue(strategyId, awardId, ruleModel);
    }

    @Override
    public StrategyAwardRuleModelVO queryStrategyAwardRuleModelVO(Long strategyId, Integer awardId) {
        String ruleModels = strategyAwardDao.queryStrategyAwardRuleModels(strategyId, awardId);
        return StrategyAwardRuleModelVO.builder()
                .ruleModels(ruleModels)
                .build();
    }
}
